package com.jeesite.modules.topiam.web;

import com.jeesite.common.mapper.JsonMapper;
import com.jeesite.common.shiro.authc.FormToken;
import com.jeesite.common.shiro.filter.FormFilter;
import com.jeesite.common.web.BaseController;
import com.jeesite.common.web.http.ServletUtils;
import com.jeesite.modules.sys.utils.UserUtils;
import com.jeesite.modules.topiam.oauth.AuthTopIamRequest;
import com.jeesite.modules.topiam.service.TopIamOauth2Service;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * TOPIAM OAuth2 Controller
 *
 * @author TopIAM
 * Created by support@topiam.cn on  2023/08/30 13:11
 */
@Controller
@RequestMapping({"/oauth2"})
public class TopIamOauth2Controller extends BaseController {

    /**
     * topiam login
     *
     * @param request {@link HttpServletRequest}
     * @return {@link String}
     */
    @RequestMapping({"/login/topiam"})
    public String login(HttpServletRequest request) {
        logger.debug("Redirect topiam authentication");
        return "redirect:" + getAuthTopIamRequest().authorize((request.getParameter("state") == null ? AuthStateUtils.createState() : request.getParameter("state")));
    }

    /**
     * TopIAM callback
     *
     * @param callback {@link AuthCallback}
     */
    @RequestMapping({"/callback/topiam"})
    public void callback(AuthCallback callback) {
        logger.debug("Reception topiam callback");
        AuthResponse<?> rauthResponse = getAuthTopIamRequest().login(callback);
        AuthUser authUser = (AuthUser) rauthResponse.getData();
        logger.debug("Get topiam result: {}", JsonMapper.toJson(authUser));
        HttpServletRequest request = ServletUtils.getRequest();
        HttpServletResponse response = ServletUtils.getResponse();
        try {
            // FormToken 构造方法的三个参数：登录名、是否内部登录无条件、请求对象
            UserUtils.getSubject().login(new FormToken(topIamOauth2Service.getSysUserCode(authUser), true, request));
            logger.debug("Authentication success, __sid={}", UserUtils.getSession().getId());
            FormFilter.onLoginSuccess(request, response);
        } catch (AuthenticationException e) {
            FormFilter.onLoginFailure(e, request, response);
        }
    }


    public AuthTopIamRequest getAuthTopIamRequest() {
        return topIamOauth2Service.getAuthTopIamRequest();
    }

    private final TopIamOauth2Service topIamOauth2Service;

    public TopIamOauth2Controller(TopIamOauth2Service topIamOauth2Service) {
        this.topIamOauth2Service = topIamOauth2Service;
    }
}
